import re  
import logging

from agent.common.system import sysCommand
from agent.domain.base import BaseDomain

logger = logging.getLogger('common')

class Grub(BaseDomain):
    """ Configure grub parameter by grubby
    
    [grub]
    nospectre_bhb = on
    """
    __domain__ = "grub"
    
    __load_kernel__ = "grubby --default-kernel"
    __kernel_info__ = "grubby --info={kernel_name}"
    __append_args__ = "grubby --update-kernel={kernel_name} --args={param_name}"
    __remove_args__ = "grubby --update-kernel={kernel_name} --remove-args={param_name}"
    
    def __init__(self):
        super().__init__(domain_name = self.__domain__)
        self.default_kernel = sysCommand(self.__load_kernel__)
        logger.info("default kernel: {}".format(self.default_kernel))
    
    def set_value(self, param_name:str, param_value):
        current_value = self.get_value(param_name)
        if param_value == current_value:
            return
        
        if param_value == "off" and current_value == "on":
            sysCommand(self.__remove_args__.format(
                kernel_name = self.default_kernel,
                param_name = param_name,
            ))
            sysCommand(self.__append_args__.format(
                kernel_name = self.default_kernel,
                param_name = "no" + param_name,
            ))
            
        elif param_value == "off" and current_value == "default":
            sysCommand(self.__append_args__.format(
                kernel_name = self.default_kernel,
                param_name = "no" + param_name,
            ))
            
        elif param_value == "on" and current_value == "off":
            sysCommand(self.__remove_args__.format(
                kernel_name = self.default_kernel,
                param_name = "no" + param_name,
            ))
            sysCommand(self.__append_args__.format(
                kernel_name = self.default_kernel,
                param_name = param_name,
            ))
            
        elif param_value == "on" and current_value == "default":
            sysCommand(self.__append_args__.format(
                kernel_name = self.default_kernel,
                param_name = param_name,
            ))
            
        elif param_value == "default" and current_value == "on":
            sysCommand(self.__remove_args__.format(
                kernel_name = self.default_kernel,
                param_name = param_name,
            ))
            
        elif param_value == "default" and current_value == "off":
            sysCommand(self.__remove_args__.format(
                kernel_name = self.default_kernel,
                param_name = "no" + param_name,
            ))
        raise Exception("Grub: Reboot your system to apply changes. ")
    
    def get_value(self, param_name:str):
        """ read param current value by
        
        grubby --info=[default_kernel]
        """
        kernel_info = sysCommand("grubby --info={}".format(self.default_kernel))
        args_info = re.search("args=\"(.*)\"", kernel_info).group(1)
        if re.search("no{}".format(param_name), args_info):
            return "off"
        elif re.search("{}".format(param_name), args_info):
            return "on"
        else:
            return "default"

if __name__ == "__main__":
    g = Grub()
    g.backup({"spectre_bhb":{'value':'on'}})
    
    g.set_value("spectre_bhb", "default")
    print(g.get_value("spectre_bhb"))
    
    g.set_value("spectre_bhb", "on")
    print(g.get_value("spectre_bhb"))
    
    g.set_value("spectre_bhb", "off")
    print(g.get_value("spectre_bhb"))
    
    g.set_value("spectre_bhb", "on")
    print(g.get_value("spectre_bhb"))
    
    g.set_value("spectre_bhb", "default")
    print(g.get_value("spectre_bhb"))
        
    g.set_value("spectre_bhb", "off")
    print(g.get_value("spectre_bhb"))
    
    g.set_value("spectre_bhb", "default")
    print(g.get_value("spectre_bhb"))
    g.rollback()